﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WordRacer.Domain.Model.Dictionaries;
using WordRacer.Domain.Model.Boards;
using WordRacer.Domain.Model.GameCells;

/// <summary>
///             + --- + --- +                            + --- + --- + 
///             |  D  |  C  |                            |  1  |  2  |     
///       + --- + --- + --- + --- +                + --- + --- + --- + --- +
///       |  L  |  W  |  Y  |  B  |                |  3  |  4  |  5  |  6  |     
/// + --- + --- + --- + --- + --- + --- +    + --- + --- + --- + --- + --- + --- +
/// |  H  |  K  |  X  |  C  |  S  |  E  |    |  7  |  8  |  9  |  10 |  11 |  12 |
/// + --- + --- + --- + --- + --- + --- +    + --- + --- + --- + --- + --- + --- +
/// |  N  |  I  |  T  |  R  |  E  |  E  |    |  13 |  14 |  15 |  16 |  17 |  18 |
/// + --- + --- + --- + --- + --- + --- +    + --- + --- + --- + --- + --- + --- +
///       |  E  |  H  |  A  |  O  |                |  19 |  20 | 21  |  22 |     
///       + --- + --- + --- + --- +                + --- + --- + --- + --- + 
///             |  I  |  D  |                            |  23 | 24  |          
///             + --- + --- +                            + --- + --- +  
/// </summary>



namespace WordRacer.Domain.Tests.Integration.Fixtures
{
  public class Round2BoardBuilder
  {
    private IGameDictionary _gameDictionary;
    private bool GameDictionaryProvided = false;
    private char _cell1Letter = 'D'; 
    private char _cell2Letter = 'C';
    private char _cell3Letter = 'L';
    private char _cell4Letter = 'W';
    private char _cell5Letter = 'Y';
    private char _cell6Letter = 'B';
    private char _cell7Letter = 'H';
    private char _cell8Letter = 'K';
    private char _cell9Letter = 'X';
    private char _cell10Letter = 'C';
    private char _cell11Letter = 'S';
    private char _cell12Letter = 'E';
    private char _cell13Letter = 'N';
    private char _cell14Letter = 'I';
    private char _cell15Letter = 'T';
    private char _cell16Letter = 'R';
    private char _cell17Letter = 'E';
    private char _cell18Letter = 'E';
    private char _cell19Letter = 'E';
    private char _cell20Letter = 'H';
    private char _cell21Letter = 'A';
    private char _cell22Letter = 'O';
    private char _cell23Letter = 'I';
    private char _cell24Letter = 'D';
    private GameCellFactory _gameCellFactory;

    public Round2BoardBuilder()
    {
      _gameCellFactory = new GameCellFactory();
      GameDictionaryProvided = false;
    }

    public Board Build()
    {
      if(!GameDictionaryProvided)
      {
        _gameDictionary = BuildBaseDictionary();
      }

      var gameBoardFactory = new BoardFactory();
      var testBoard = gameBoardFactory.CreateGameBoard(_gameDictionary);

      var cellFactory = new GameCellFactory();

      //row 1 
      var cell1 = cellFactory.CreateGameCell();
      cell1.Character = _cell1Letter.ToString();
      var cell2 = cellFactory.CreateGameCell();
      cell2.Character = _cell2Letter.ToString();
      //row 2
      var cell3 = cellFactory.CreateGameCell();
      cell3.Character = _cell3Letter.ToString();
      var cell4 = cellFactory.CreateGameCell();
      cell4.Character = _cell4Letter.ToString();
      var cell5 = cellFactory.CreateGameCell();
      cell5.Character = _cell5Letter.ToString();
      var cell6 = cellFactory.CreateGameCell();
      cell6.Character = _cell6Letter.ToString();
      //row 3
      var cell7 = cellFactory.CreateGameCell();
      cell7.Character = _cell7Letter.ToString();
      var cell8 = cellFactory.CreateGameCell();
      cell8.Character = _cell8Letter.ToString();
      var cell9 = cellFactory.CreateGameCell();
      cell9.Character = _cell9Letter.ToString();
      var cell10 = cellFactory.CreateGameCell();
      cell10.Character = _cell10Letter.ToString();
      var cell11 = cellFactory.CreateGameCell();
      cell11.Character = _cell11Letter.ToString();
      var cell12 = cellFactory.CreateGameCell();
      cell12.Character = _cell12Letter.ToString();
      //row 4
      var cell13 = cellFactory.CreateGameCell();
      cell13.Character = _cell13Letter.ToString();
      var cell14 = cellFactory.CreateGameCell();
      cell14.Character = _cell14Letter.ToString();
      var cell15 = cellFactory.CreateGameCell();
      cell15.Character = _cell15Letter.ToString();
      var cell16 = cellFactory.CreateGameCell();
      cell16.Character = _cell16Letter.ToString();
      var cell17 = cellFactory.CreateGameCell();
      cell17.Character = _cell17Letter.ToString();
      var cell18 = cellFactory.CreateGameCell();
      cell18.Character = _cell18Letter.ToString();
      //row 5
      var cell19 = cellFactory.CreateGameCell();
      cell19.Character = _cell19Letter.ToString();
      var cell20 = cellFactory.CreateGameCell();
      cell20.Character = _cell20Letter.ToString();
      var cell21 = cellFactory.CreateGameCell();
      cell21.Character = _cell21Letter.ToString();
      var cell22 = cellFactory.CreateGameCell();
      cell22.Character = _cell22Letter.ToString();
      //row 6
      var cell23 = cellFactory.CreateGameCell();
      cell23.Character = _cell23Letter.ToString();
      var cell24 = cellFactory.CreateGameCell();
      cell24.Character = _cell24Letter.ToString();

      //add cells to board
      testBoard.AddGameCell(cell1);
      testBoard.AddGameCell(cell2);
      testBoard.AddGameCell(cell3);
      testBoard.AddGameCell(cell4);
      testBoard.AddGameCell(cell5);
      testBoard.AddGameCell(cell6);
      testBoard.AddGameCell(cell7);
      testBoard.AddGameCell(cell8);
      testBoard.AddGameCell(cell9);
      testBoard.AddGameCell(cell10);
      testBoard.AddGameCell(cell11);
      testBoard.AddGameCell(cell12);
      testBoard.AddGameCell(cell13);
      testBoard.AddGameCell(cell14);
      testBoard.AddGameCell(cell15);
      testBoard.AddGameCell(cell16);
      testBoard.AddGameCell(cell17);
      testBoard.AddGameCell(cell18);
      testBoard.AddGameCell(cell19);
      testBoard.AddGameCell(cell20);
      testBoard.AddGameCell(cell21);
      testBoard.AddGameCell(cell22);
      testBoard.AddGameCell(cell23);
      testBoard.AddGameCell(cell24);

      //now connect the cells to each other
      //row 1
      testBoard.ConnectTwoCells(cell1, cell2);
      testBoard.ConnectTwoCells(cell1, cell3);
      testBoard.ConnectTwoCells(cell1, cell4);
      testBoard.ConnectTwoCells(cell1, cell5);
      testBoard.ConnectTwoCells(cell2, cell4);
      testBoard.ConnectTwoCells(cell2, cell5);
      testBoard.ConnectTwoCells(cell2, cell6);
      //row 2
      testBoard.ConnectTwoCells(cell3, cell4);
      testBoard.ConnectTwoCells(cell3, cell7);
      testBoard.ConnectTwoCells(cell3, cell8);
      testBoard.ConnectTwoCells(cell3, cell9);

      testBoard.ConnectTwoCells(cell4, cell5);
      testBoard.ConnectTwoCells(cell4, cell8);
      testBoard.ConnectTwoCells(cell4, cell9);
      testBoard.ConnectTwoCells(cell4, cell10);

      testBoard.ConnectTwoCells(cell5, cell6);
      testBoard.ConnectTwoCells(cell5, cell9);
      testBoard.ConnectTwoCells(cell5, cell10);
      testBoard.ConnectTwoCells(cell5, cell11);

      testBoard.ConnectTwoCells(cell6, cell10);
      testBoard.ConnectTwoCells(cell6, cell11);
      testBoard.ConnectTwoCells(cell6, cell12);

      //row 3
      testBoard.ConnectTwoCells(cell7, cell8);
      testBoard.ConnectTwoCells(cell7, cell13);
      testBoard.ConnectTwoCells(cell7, cell14);

      testBoard.ConnectTwoCells(cell8, cell9);
      testBoard.ConnectTwoCells(cell8, cell13);
      testBoard.ConnectTwoCells(cell8, cell14);
      testBoard.ConnectTwoCells(cell8, cell15);

      testBoard.ConnectTwoCells(cell9, cell10);
      testBoard.ConnectTwoCells(cell9, cell14);
      testBoard.ConnectTwoCells(cell9, cell15);
      testBoard.ConnectTwoCells(cell9, cell16);

      testBoard.ConnectTwoCells(cell10, cell11);
      testBoard.ConnectTwoCells(cell10, cell15);
      testBoard.ConnectTwoCells(cell10, cell16);
      testBoard.ConnectTwoCells(cell10, cell17);

      testBoard.ConnectTwoCells(cell11, cell12);
      testBoard.ConnectTwoCells(cell11, cell16);
      testBoard.ConnectTwoCells(cell11, cell17);
      testBoard.ConnectTwoCells(cell11, cell18);

      testBoard.ConnectTwoCells(cell12, cell17);
      testBoard.ConnectTwoCells(cell12, cell18);

      //row 4
      testBoard.ConnectTwoCells(cell13, cell14);
      testBoard.ConnectTwoCells(cell13, cell19);

      testBoard.ConnectTwoCells(cell14, cell15);
      testBoard.ConnectTwoCells(cell14, cell19);
      testBoard.ConnectTwoCells(cell14, cell20);

      testBoard.ConnectTwoCells(cell15, cell16);
      testBoard.ConnectTwoCells(cell15, cell19);
      testBoard.ConnectTwoCells(cell15, cell20);
      testBoard.ConnectTwoCells(cell15, cell21);

      testBoard.ConnectTwoCells(cell16, cell17);
      testBoard.ConnectTwoCells(cell16, cell20);
      testBoard.ConnectTwoCells(cell16, cell21);
      testBoard.ConnectTwoCells(cell16, cell22);

      testBoard.ConnectTwoCells(cell17, cell18);
      testBoard.ConnectTwoCells(cell17, cell21);
      testBoard.ConnectTwoCells(cell17, cell22);

      testBoard.ConnectTwoCells(cell18, cell22);

      //row 5
      testBoard.ConnectTwoCells(cell19, cell20);
      testBoard.ConnectTwoCells(cell19, cell23);

      testBoard.ConnectTwoCells(cell20, cell21);
      testBoard.ConnectTwoCells(cell20, cell23);
      testBoard.ConnectTwoCells(cell20, cell24);

      testBoard.ConnectTwoCells(cell21, cell22);
      testBoard.ConnectTwoCells(cell21, cell23);
      testBoard.ConnectTwoCells(cell21, cell24);

      testBoard.ConnectTwoCells(cell22, cell24);

      //row 6
      testBoard.ConnectTwoCells(cell23, cell24);      

      return testBoard;
    }

    private GameDictionary BuildBaseDictionary()
    {
      var dictionaryFactory = new DictionaryFactory();
      var baseDictionary = dictionaryFactory.CreateGameDictionary();
      baseDictionary.AddWord("ESS");
      baseDictionary.AddWord("ORT");
      baseDictionary.AddWord("BEE");
      baseDictionary.AddWord("GIT");
      baseDictionary.AddWord("NOG");
      baseDictionary.AddWord("SEAR");
      baseDictionary.AddWord("TREE");
      baseDictionary.AddWord("KIT");
      baseDictionary.AddWord("LOO");
      baseDictionary.AddWord("NOB");
      baseDictionary.AddWord("BOT");
      baseDictionary.AddWord("DREG");
      baseDictionary.AddWord("AMIDS");
      baseDictionary.AddWord("UNARY");
      baseDictionary.AddWord("LOUTED");
      baseDictionary.AddWord("CUSPED");
      baseDictionary.AddWord("CADES");
      baseDictionary.AddWord("CELS");
      baseDictionary.AddWord("NICHED");
      baseDictionary.AddWord("TOPE");
      baseDictionary.AddWord("DUKED");
      baseDictionary.AddWord("CURRED");
      baseDictionary.AddWord("DILLED");
      baseDictionary.AddWord("FOUGHT");
      baseDictionary.AddWord("REDOS");
      baseDictionary.AddWord("ROSED");
      baseDictionary.AddWord("NIBBED");
      baseDictionary.AddWord("DINE");
      baseDictionary.AddWord("TAR");
      baseDictionary.AddWord("FOG");
      baseDictionary.AddWord("TOFU");
      baseDictionary.AddWord("DEN");
      baseDictionary.AddWord("DIN");
      baseDictionary.AddWord("END");
      baseDictionary.AddWord("BIN");
      baseDictionary.AddWord("NIB");
      baseDictionary.AddWord("BEND");
      baseDictionary.AddWord("BIND");
      baseDictionary.AddWord("SEW");
      baseDictionary.AddWord("WEAN");
      return baseDictionary;
    }

    private GameCell BuildGameCell(char letter)
    {
      var gameCell = _gameCellFactory.CreateGameCell();
      gameCell.Character = letter.ToString().ToUpper();
      return gameCell;
    }

    public Round2BoardBuilder WithDictionary(IGameDictionary gameDictionary)
    {
      _gameDictionary = gameDictionary;
      GameDictionaryProvided = true;
      return this;
    }

    public Round2BoardBuilder WithCell1Character(char letter)
    {
      _cell1Letter = letter;
      return this;
    }

    public Round2BoardBuilder WithCell2Character(char letter)
    {
      _cell2Letter = letter;
      return this;
    }

    public Round2BoardBuilder WithCell3Character(char letter)
    {
      _cell3Letter = letter;
      return this;
    }

    public Round2BoardBuilder WithCell4Character(char letter)
    {
      _cell4Letter = letter;
      return this;
    }

    public Round2BoardBuilder WithCell5Character(char letter)
    {
      _cell5Letter = letter;
      return this;
    }

    public Round2BoardBuilder WithCell6Character(char letter)
    {
      _cell6Letter = letter;
      return this;
    }

    public Round2BoardBuilder WithCell7Character(char letter)
    {
      _cell7Letter = letter;
      return this;
    }

    public Round2BoardBuilder WithCell8Character(char letter)
    {
      _cell8Letter = letter;
      return this;
    }

    public Round2BoardBuilder WithCell9Character(char letter)
    {
      _cell9Letter = letter;
      return this;
    }

    public Round2BoardBuilder WithCell10Character(char letter)
    {
      _cell10Letter = letter;
      return this;
    }

    public Round2BoardBuilder WithCell11Character(char letter)
    {
      _cell11Letter = letter;
      return this;
    }

    public Round2BoardBuilder WithCell12Character(char letter)
    {
      _cell12Letter = letter;
      return this;
    }

    public Round2BoardBuilder WithCell13Character(char letter)
    {
      _cell13Letter = letter;
      return this;
    }

    public Round2BoardBuilder WithCell14Character(char letter)
    {
      _cell14Letter = letter;
      return this;
    }

    public Round2BoardBuilder WithCell15Character(char letter)
    {
      _cell15Letter = letter;
      return this;
    }

    public Round2BoardBuilder WithCell16Character(char letter)
    {
      _cell16Letter = letter;
      return this;
    }

    public Round2BoardBuilder WithCell17Character(char letter)
    {
      _cell17Letter = letter;
      return this;
    }

    public Round2BoardBuilder WithCell18Character(char letter)
    {
      _cell18Letter = letter;
      return this;
    }

    public Round2BoardBuilder WithCell19Character(char letter)
    {
      _cell19Letter = letter;
      return this;
    }

    public Round2BoardBuilder WithCell20Character(char letter)
    {
      _cell20Letter = letter;
      return this;
    }

    public Round2BoardBuilder WithCell21Character(char letter)
    {
      _cell21Letter = letter;
      return this;
    }

    public Round2BoardBuilder WithCell22Character(char letter)
    {
      _cell22Letter = letter;
      return this;
    }

    public Round2BoardBuilder WithCell23Character(char letter)
    {
      _cell23Letter = letter;
      return this;
    }

    public Round2BoardBuilder WithCell24Character(char letter)
    {
      _cell24Letter = letter;
      return this;
    }

  }
}
